﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using EasyTools.ImageTool;

namespace EasyTools.UI
{
    public partial class FileSplitFrm : Form
    {
        public FileSplitFrm()
        {
            InitializeComponent();
            comboBox1.SelectedIndex = 1;
        }

        private void textBox1_DoubleClick(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                textBox1.Text = openFileDialog1.FileName;
            }
        }
        static byte MASK = 151;
        private void button1_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                using (FileSplit fs = new FileSplit(textBox1.Text))
                {
                    int x = 1024;
                    int index = comboBox1.SelectedIndex;
                    while (index-- != 0)
                    {
                        x *= 1024;
                    }
                    fs.Split(int.Parse(textBox2.Text) * x, folderBrowserDialog1.SelectedPath);
                }
            }
        }

        private void textBox3_DoubleClick(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                textBox3.Text = folderBrowserDialog1.SelectedPath;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                using (FileSplit fs = new FileSplit())
                {

                    fs.Connect(textBox3.Text, saveFileDialog1.FileName);
                }
            }
        }

        private void textBox4_Click(object sender, EventArgs e)
        {
            var res = openFileDialog1.ShowDialog();
            if(res != DialogResult.OK && res != DialogResult.Yes)
            {
                return;
            }
            textBox4.Text = openFileDialog1.FileName;

        }

        private void textBox5_Click(object sender, EventArgs e)
        {
            var res = openFileDialog1.ShowDialog();
            if (res != DialogResult.OK && res != DialogResult.Yes)
            {
                return;
            }
            textBox5.Text = openFileDialog1.FileName;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            var info = new FileInfo(textBox4.Text);
            var fi = File.OpenRead(textBox4.Text);
            
            var cache = new byte[255];
            var fo = File.OpenWrite(textBox4.Text + ".mask");
            var fileNameData = Encoding.UTF8.GetBytes(info.Name);
            fo.Write(fileNameData,0, fileNameData.Length);
            fo.WriteByte(0);
            fo.Write(BitConverter.GetBytes(info.Length), 0, 8);
            while (true) {
                var readL = fi.Read(cache, 0, cache.Length);
                if (readL <= 0)
                {
                    fi.Close();
                    fo.Close();
                    break;
                }
                for (int i = 0; i < readL; i++)
                {
                    cache[i] ^= MASK;

                }
                var post = 0;
                for (int i = 0; i < readL-3; i++)
                {                    
                    var j = i;
                    for(;j<readL; j++)
                    {
                        if (cache[j] != cache[i])
                        {
                            break;
                        }
                    }
                    // 可压缩
                    if (j - i > 3)
                    {
                        // 未压缩的数据
                        if (i-post> 0)
                        {
                            fo.WriteByte((byte)'S');
                            var slen = i - post;
                            fo.WriteByte((byte)slen);
                            fo.Write(cache, post, slen);
                        }

                        fo.WriteByte((byte)'Z');
                        var zlen = j - i;
                        fo.WriteByte((byte)zlen);
                        fo.WriteByte(cache[i]);
                        post = j;
                        i = j;
                    }
                }
                if (post < readL)
                {
                    fo.WriteByte((byte)'S');
                    var slen = readL - post;
                    fo.WriteByte((byte)slen);
                    fo.Write(cache, post, slen);
                }
            }


        }

        private void button4_Click(object sender, EventArgs e)
        {
            var info = new FileInfo(textBox5.Text);
            var fi = File.OpenRead(textBox5.Text);

            var nameBuffer = new byte[1024*100];
            int len = 0;
            for (int i = 0; i < nameBuffer.Length; i++)
            {
                int d = fi.ReadByte();
                if (d == 0)
                {
                    break;
                }
                nameBuffer[i] = (byte)d;
                len = i;
            }
            string sname = Encoding.UTF8.GetString(nameBuffer, 0, len+1);
            var of = Path.Combine(info.DirectoryName, sname);
            var rti = 0;
            while (File.Exists(of))
            {
                of = Path.Combine(info.DirectoryName, "(" + (rti++) + ")" + sname);

            }
            

            var fo = File.OpenWrite(of);

            fi.Read(nameBuffer, 0, 8);
            long fileLen = BitConverter.ToInt64(nameBuffer, 0);

            while (true)
            {
                var sb = fi.ReadByte();
                if (sb < 0)
                {
                    break;
                }
                var tp = (char)sb;
                var clen = fi.ReadByte();
                if (tp == 'S')
                {
                    fi.Read(nameBuffer, 0, clen);
                }
                else
                {
                    var datac = (byte)fi.ReadByte();
                    for (int i = 0; i < clen; i++)
                    {
                        nameBuffer[i] = datac;
                    }                    
                }
                mask(nameBuffer, 0, clen);
                fo.Write(nameBuffer, 0, clen);
            }
            fi.Close();
            fo.Close();

        }
        byte[] mask(byte[] s,int pos,int len)
        {
            for (int i = 0; i < pos+len; i++)
            {
                s[i] ^= MASK;
            }
            return s;
        }
    }
}
